#pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>

// #define SELF 1

const std::string ProtSep = " ";
const std::string Sep = "\r\n";

// {json} -> len\r\n{json}\r\n
bool Encode(std::string& message)
{
    if (message.size() == 0) return false;
    std::string package = std::to_string(message.size()) + Sep + message + Sep;
    message = package;
    return true;
}

// len\r\n{json}\r\n 
// 123\r\n{json}\r\n -> {json}  
// 123\r\n 
// 123\r\n{jso
// 123\r\n{json}\r
// 123\r\n{json}\r\n123\r\n{json}\r\n123\r\n{j
bool Decode(std::string& package, std::string* content)
{
    auto pos = package.find(Sep);
    if (pos == std::string::npos) return false;
    std::string content_length_str = package.substr(0, pos);
    int content_length = std::stoi(content_length_str);
    int full_length = content_length_str.size() + content_length + Sep.size() * 2;

    if (package.size() < full_length) return false;
        
    *content = package.substr(pos + Sep.size(), content_length);

    // package earse
    package.erase(0, full_length);
    return true;
}

class Request
{
public:
    Request()
    :_x(0)
    ,_y(0)
    ,_oper(0)
    {}

    Request(int x, int y, char oper)
    :_x(x)
    ,_y(y)
    ,_oper(oper)
    {}

    bool Serialize(std::string& out_string)
    {
#ifdef SELF
        // ->"x oper y" 以空格间隔
        std::string x_string = std::to_string(_x);
        std::string y_string = std::to_string(_y);
        out_string = x_string + ProtSep + _oper + ProtSep + y_string;
        return true;
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::StreamWriterBuilder wbuilder;
        std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter());
        std::stringstream ss;
        writer->write(root, &ss);
        out_string = ss.str();
        return true;
#endif
    }

    bool Deserialize(std::string& in_string)
    {
#ifdef SELF
        // "x oper y" ->提取出x、opear、y
        auto left = in_string.find(ProtSep);
        if (left == std::string::npos) return false;
        auto right = in_string.rfind(ProtSep);
        if (right == std::string::npos) return false;

        if (left + ProtSep.size() + 1 != right) return false;

        std::string x_string = in_string.substr(0, left);
        if (x_string.empty()) return false;

        std::string y_string = in_string.substr(right + ProtSep.size());
        if (y_string.empty()) return false;

        _x = std::stoi(x_string);
        _y = std::stoi(y_string);
        _oper = in_string[right-1];
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(in_string, root);
        if (!parsingSuccessful)
        {
            std::cout << "Filed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
#endif
    }

    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _y << std::endl;
        std::cout << _oper << std::endl;
    }

    int X() const { return _x; }
    int Y() const { return _y; }
    char Oper() const { return _oper; }
private:
    int _x;
    int _y;
    char _oper;
};


class Response
{
public:
    Response()
    :_result(0)
    ,_code(0)
    {}

    Response(int result, int code)
    :_result(result)
    ,_code(code)
    {}

    bool Serialize(std::string& out_string)
    {
#ifdef SELF
        // 结构化数据 -> "result code"
        std::string result_string = std::to_string(_result);
        std::string code_string = std::to_string(_code);
        out_string = result_string + ProtSep + code_string;
        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StreamWriterBuilder wbuilder;
        std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter());
        std::stringstream ss;
        writer->write(root, &ss);
        out_string = ss.str();
        return true;
#endif
    }

    bool Deserialize(std::string& in_string)
    {
#ifdef SELF
        // "result code" -> 结构化数据
        auto pos = in_string.find(ProtSep);
        if (pos == std::string::npos) return false;

        std::string result_string = in_string.substr(0, pos);
        if (result_string.empty()) return false;
        std::string code_string = in_string.substr(pos + ProtSep.size());
        if (code_string.empty()) return false;

        _result = std::stoi(result_string);
        _code = std::stoi(code_string);
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(in_string, root);
        if (!parsingSuccessful)
        {
            std::cout << "Filed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
#endif
    }

    int Result() const { return _result; }
    int Code() const { return _code; }
    void SetResult(int result) { _result = result; }
    void SetCode(int code) { _code = code; }
private:
    int _result;  // 结果
    int _code;    // 出错码,0,1,2,...
};